#include "Game.h"
#include "FlexiApplication.h"
#include "TaskManager.h"
#include "PhysicsTask.h"
#include "UpdateTask.h"
#include "CombatTask.h"
#include "CombatSystem.h"
#include "MdlFileLoader.h"
#include "ObjModelFile.h"
#include "ModelFactory.h"
#include "Settings.h"
#include "Texture.h"
#include "LoadTGA.h"
#include "IRenderer.h"
#include "Library.h"
#include "BoundingBox.h"
#include "BoundingSphere.h"
#include "TriangleMesh.h"
#include "Serialize.h"
#include "MS3DModelLoader.h"
#include "ShaderFactory.h"

IBehavior::CreatorMap_t Game::m_behaviorCreators;
Combat::IAbility::CreatorMap_t Game::m_abilityCreators;
Combat::IEffect::CreatorMap_t Game::m_effectCreators;
IUniformInstruction::CreatorMap_t Game::m_uniformInstructions;

void Game::Initialize()
{
	new Combat::System();

	FlexiApplication::getSingleton().physics = Pointer<ITask>(new PhysicsTask());
	FlexiApplication::getSingleton().update = Pointer<ITask>(new UpdateTask());
	FlexiApplication::getSingleton().combat = Pointer<ITask>(new CombatTask());

	TaskManager::getSingleton().AddTask(FlexiApplication::getSingleton().physics);
	TaskManager::getSingleton().AddTask(FlexiApplication::getSingleton().update);
	TaskManager::getSingleton().AddTask(FlexiApplication::getSingleton().combat);
	
	m_selectables = new System();
	m_selectables->Initialize();

	LoadDefaults();
	LoadFromFile("version6.xml");
}
void Game::Deinitialize()
{
	delete Combat::System::getSingletonPtr();
}
void Game::LoadDefaults()
{
	Renderer->BuildFont(HashedString("Arial"), 10);
	
	MdlFile modelFile;
	ObjModelFile file;
	LoadObjModelFile((Settings::getSingleton().getDirectory() + "//Data//Models//sphere.obj").c_str(), file );
	ConvertToMdlFile(file, modelFile);
	modelFile.modelName = "Default";
	//LoadMdlFile(std::string(Settings::getSingleton().getDirectory() + "//Data//Models//cube.mdl"), modelFile );
	CreateModelFromMdl(modelFile);
	CreateSimulationWorld(HashedString("Default"));
	//CreatePathingWorld(HashedString("DefaultPathing"));

	CreateShader((Settings::getSingleton().getDirectory() + "//Data//Shaders//SkeletalShader.shd"));
	//CreateShader((Settings::getSingleton().getDirectory() + "//Data//Shaders//ShaderScript.shd"));
	bool success = LoadGraphicResourceXML((Settings::getSingleton().getDirectory() + "//Data//Models//triangle.xml").c_str());
	success = LoadGraphicResourceXML((Settings::getSingleton().getDirectory() + "//Data//Models//zombie02.xml").c_str());
	//skeleton = CreateSkeletonFromSkl(sklFile);
}

bool Game::LoadTexture( std::string filename )
{
	int extIndex = filename.find_last_of('.');
	std::string extension = filename.substr(extIndex + 1);
	int lastWord = filename.find_last_of("\\/");
	std::string name = filename.substr(lastWord + 1, extIndex - lastWord - 1);

	if (extension == "tga")
	{
		// Load Image
		Pointer<Image> image = new Image();
		if (!LoadTGA(std::string(Settings::getSingleton().getDirectory() + filename), *image))
			return false;;					// fail
		Texture texture(image);
		// Add texture to renderer
		Renderer->LoadTexture( HashedString(name), texture, true );
	}
	m_textureStrings.push_back(filename);
	
	return true;
}

CombatComponent* Game::CreateCombatComponent( Entity* entity, Avatar::Data::Vector_t& dataArray )
{
	CombatComponent* combat = new CombatComponent(entity);

	for (Avatar::Data::Vector_t::iterator it = dataArray.begin(); it != dataArray.end(); ++it)
	{
		Avatar::Data* data = (*it);

		if (data->getName() == HashedString("Effect"))
		{
			Combat::IEffect::CreatorMap_t::iterator creator = m_effectCreators.find(data->getValues()["Name"]);
			if (creator != m_effectCreators.end())
			{
				Pointer<Combat::IEffect> effect = (creator->second)(combat->Combatant());
				combat->Combatant()->Effects()[effect->Type()].push_back(effect);
			}
		}
		else if (data->getName() == HashedString("Ability"))
		{
			Combat::IAbility::CreatorMap_t::iterator creator = m_abilityCreators.find(data->getValues()["Name"]);
			if (creator != m_abilityCreators.end())
			{
				Pointer<Combat::IAbility> ability = (*creator->second)(combat->Combatant());
				combat->Combatant()->Abilities().push_back(ability);
			}
		}
	}
	return combat;
}
StatusComponent* Game::CreateStatusComponent( Entity* entity, Avatar::Data::Vector_t& dataArray )
{
	StatusComponent* status = new StatusComponent(entity);

	for (Avatar::Data::Vector_t::iterator it = dataArray.begin(); it != dataArray.end(); ++it)
	{
		HashedString name((*it)->getValues()["Name"]);
		HashedString value((*it)->getValues()["Value"]);

		status->getStatus(name) = atoi(value.getString().c_str());
	}

	return status;
}
OrientationComponent* Game::CreateOrientationComponent( Entity* entity, Avatar::Data::Vector_t& dataArray )
{
	OrientationComponent* orientation = new OrientationComponent(entity);
	return orientation;
}
GraphicalComponent* Game::CreateGraphicalComponent( Entity* entity, Avatar::Data::Vector_t& dataArray )
{
	GraphicalComponent* graphical = 0;
	Pointer<Model> model;
	HashedString modelName;

	for (Avatar::Data::Vector_t::iterator it = dataArray.begin(); it != dataArray.end(); ++it)
	{
		Avatar::Data* data = (*it);

		if (data->getName() == HashedString("Model"))
		{
			modelName = HashedString(data->getValues()["Name"]);
		}
	}

	Pointer<IResource> resource = Library::getSingleton().getResource(Model::type, modelName);

	// GraphicalComponent
	if (resource.isValid())
	{
		CopyPointer(resource, model);
		graphical = new GraphicalComponent(entity, model);
	}

	return graphical;
}
RigidBodyComponent* Game::CreateRigidBodyComponent( Entity* entity, Avatar::Data::Vector_t& dataArray )
{
	RigidBodyComponent* rigidbody = new RigidBodyComponent(Pointer<RigidBody>(new RigidBody(1.0f, entity)), entity);
	Pointer<IShape> mesh;

	for (Avatar::Data::Vector_t::iterator it = dataArray.begin(); it != dataArray.end(); ++it)
	{
		Avatar::Data* data = *it;

		HashedString type(data->getValues()["Type"]);
				
		if (type == BoundingSphere::type || type == HashedString("Sphere"))
		{
			HashedString radiusString(data->getValues()["Radius"]);
			float radius = (float)atof(radiusString.getString().c_str());

			BoundingSphere* sphere = new BoundingSphere(radius);
			mesh = sphere;
		}
		if (type == TriangleMesh::type)					// Must be static
		{
			GraphicalComponent* graphical = (GraphicalComponent*)(entity->FindComponent(GraphicalComponent::type));
			ModelNode* modelNode = (ModelNode*)((INode*)graphical->getNode());
			Model* model = modelNode->getModelInstance()->getModel();
			Mesh::Vector_t& meshes = model->getMeshes();

			for (Mesh::Vector_t::iterator it = meshes.begin(); it != meshes.end(); ++it)
			{
				unsigned int offset, size, vertSize = (*it)->getVertexContainer()->getVertexDeclaration().m_vertexSize;
#pragma region FIND_ENUMPOSITION
				{
					const VertexType::Vector_t& params = (*it)->getVertexContainer()->getVertexDeclaration().m_parameters;
					unsigned int paramSize = params.size();

					for (unsigned int i = 0; i < paramSize; ++i)
					{
						if (params[i].m_parameter == enumPosition)
						{
							offset = params[i].m_offset;
							size = params[i].m_size;
							break;
						}
					}
				}
#pragma endregion

				std::vector<float> verts;

				unsigned char* ptr = (unsigned char*)((*it)->getVertexContainer()->getVertexPointer()) + offset;
				unsigned int count = (*it)->getVertexContainer()->getVerticeCount();

				for (unsigned int i = 0; i < count; ++i)		// for each vertex
				{
					for (unsigned int j = 0; j < size; ++j)
						verts.push_back(*(((float*)ptr) + j));
					ptr += vertSize;
				}

				mesh = new TriangleMesh(&verts[0], count/3);
				rigidbody->getBody()->setMass(0.0f);
			}
		}
		if (mesh.isValid())
		{
			rigidbody->getBody()->AddShape(mesh);
		}
	}
	return rigidbody;
}
SelectableComponent* Game::CreateSelectableComponent( Entity* entity, Avatar::Data::Vector_t& dataArray )
{
	SelectableComponent* selectable = new SelectableComponent(Pointer<RigidBody>(new RigidBody(1.0f, entity)), entity);
	Pointer<IShape> mesh;

	for (Avatar::Data::Vector_t::iterator it = dataArray.begin(); it != dataArray.end(); ++it)
	{
		Avatar::Data* data = *it;

		HashedString type(data->getValues()["Type"]);
				
		if (type == BoundingSphere::type || type == HashedString("Sphere"))
		{
			HashedString radiusString(data->getValues()["Radius"]);
			float radius = (float)atof(radiusString.getString().c_str());

			BoundingSphere* sphere = new BoundingSphere(radius);
			mesh = sphere;
		}
		if (type == TriangleMesh::type)					// Must be static
		{
			GraphicalComponent* graphical = (GraphicalComponent*)(entity->FindComponent(GraphicalComponent::type));
			ModelNode* modelNode = (ModelNode*)((INode*)graphical->getNode());
			Model* model = modelNode->getModelInstance()->getModel();
			Mesh::Vector_t& meshes = model->getMeshes();

			for (Mesh::Vector_t::iterator it = meshes.begin(); it != meshes.end(); ++it)
			{
				unsigned int offset, size, vertSize = (*it)->getVertexContainer()->getVertexDeclaration().m_vertexSize;
#pragma region FIND_ENUMPOSITION
				{
					const VertexType::Vector_t& params = (*it)->getVertexContainer()->getVertexDeclaration().m_parameters;
					unsigned int paramSize = params.size();

					for (unsigned int i = 0; i < paramSize; ++i)
					{
						if (params[i].m_parameter == enumPosition)
						{
							offset = params[i].m_offset;
							size = params[i].m_size;
							break;
						}
					}
				}
#pragma endregion

				std::vector<float> verts;

				unsigned char* ptr = (unsigned char*)((*it)->getVertexContainer()->getVertexPointer()) + offset;
				unsigned int count = (*it)->getVertexContainer()->getVerticeCount();

				for (unsigned int i = 0; i < count; ++i)		// for each vertex
				{
					for (unsigned int j = 0; j < size; ++j)
						verts.push_back(*(((float*)ptr) + j));
					ptr += vertSize;
				}

				mesh = new TriangleMesh(&verts[0], count/3);
				selectable->getBody()->setMass(0.0f);
			}
		}
		if (mesh.isValid())
		{
			selectable->getBody()->AddShape(mesh);
		}
	}
	return selectable;
}
EntityController* Game::CreateEntityController( Entity* entity, Avatar::Data::Vector_t& dataArray )
{
	EntityController* controller = new EntityController(entity);
	UpdateTask::getSingleton().RegisterUpdatable(controller);

	for (Avatar::Data::Vector_t::iterator it = dataArray.begin(); it != dataArray.end(); ++it)
	{
		Avatar::Data* data = (*it);
		if (data->getName() == HashedString("World"))
		{
			controller->setWorld(Game::getSingleton()._getPathingWorlds()[data->getValues()["Value"]]);
		} else if (data->getName() == HashedString("Behavior"))
		{
			HashedString behavior(data->getValues()["Type"]);
			
			IBehavior::CreatorMap_t::iterator create = m_behaviorCreators.find(behavior);

			if (create != m_behaviorCreators.end())
				controller->Behavior((*create->second)(controller));
		}
	}

	return controller;
}

bool Game::CreateEntity( HashedString avatarName, HashedString entityName )
{
	static unsigned int entityCounter = 0;

	Pointer<Entity> entity;

	return CreateEntity(avatarName, entityName, entity);
}
bool Game::CreateEntity( HashedString avatarName )
{
	static unsigned int entityCounter = 0;

	Pointer<Entity> entity;
	Pointer<Entity> test;
	char buffer[25];

	do
	{
		_itoa_s(entityCounter++, buffer, 10);
		RetrieveEntity(buffer, test);
	} while (test.isValid());

	HashedString entityName(buffer);

	return CreateEntity(avatarName, entityName, entity);
}
bool Game::CreateEntity( HashedString avatarName, Pointer<Entity>& entity )
{
	static unsigned int entityCounter = 0;

	Pointer<Entity> test;
	char buffer[25];

	do
	{
		test = 0;
		_itoa_s(entityCounter++, buffer, 10);
		RetrieveEntity(buffer, test);
	} while (test.isValid());

	HashedString entityName(buffer);

	return CreateEntity(avatarName, entityName, entity);
}
bool Game::CreateEntity( HashedString avatarName, HashedString entityName, Pointer<Entity>& entity )
{
	Pointer<IResource> resource = Library::getSingleton().getResource(Avatar::type, avatarName);

	if (!resource.isValid())
		return false;					// cannot find avatar

	entity = new Entity();
	
	GraphicalComponent* graphical = 0;
	OrientationComponent* orientation = 0;
	SelectableComponent* selectable = 0;
	RigidBodyComponent* rigidbody = 0;
	CombatComponent* combat = 0;
	StatusComponent* status = 0;

	Pointer<Avatar> avatar;
	CopyPointer(resource, avatar);

	Avatar::Data::Vector_t& components = avatar->getComponents();

	for (Avatar::Data::Vector_t::iterator it = components.begin(); it != components.end(); ++it)
	{
		Avatar::Data* data = (*it);
		const HashedString componentType(data->getValues()["Type"]);
		Avatar::Data::Vector_t& attribMap(data->getChildren());
		
		if (componentType == CombatComponent::type)
		{
			Pointer<IComponent> component = combat = CreateCombatComponent(entity, attribMap);
			entity->RegisterComponent(CombatComponent::type, component);		
		} else if (componentType == StatusComponent::type)
		{
			Pointer<IComponent> component = status = CreateStatusComponent(entity, attribMap);
			entity->RegisterComponent(StatusComponent::type, component);
		} else if (componentType == OrientationComponent::type)
		{
			Pointer<IComponent> component = orientation = CreateOrientationComponent(entity, attribMap);
			m_nodeNames[entityName] = orientation->getTransformNode();

			if (graphical && graphical->getNode())
				orientation->getTransformNode()->Push_Back(graphical->getNode());
			
			if (rigidbody)
				rigidbody->getPosition() = new DoubleValueTrigger<Maths::Vector3D>(&orientation->getPosition(), &rigidbody->getBody()->getPosition());
			
			if (selectable)
				selectable->getPosition() = new DoubleValueTriggerFunctor<Maths::Vector3D, RigidBody>(&orientation->getPosition(), &selectable->getBody()->getPosition(), selectable->getBody(), &RigidBody::setPosition);
			
			entity->RegisterComponent(OrientationComponent::type, component);
		} else if (componentType == RigidBodyComponent::type)
		{
			if (orientation)
			{
				Pointer<IComponent> component = rigidbody = CreateRigidBodyComponent(entity, attribMap);
				rigidbody->getPosition() = new DoubleValueTrigger<Maths::Vector3D>(&orientation->getPosition(), &rigidbody->getBody()->getPosition());
				entity->RegisterComponent(RigidBodyComponent::type, component);
			}
		} else if (componentType == SelectableComponent::type)
		{
			if (orientation)
			{
				Pointer<IComponent> component = selectable = CreateSelectableComponent(entity, attribMap);
				selectable->getPosition() = new DoubleValueTriggerFunctor<Maths::Vector3D, RigidBody>(&orientation->getPosition(), &selectable->getBody()->getPosition(), selectable->getBody(), &RigidBody::setPosition);
				entity->RegisterComponent(SelectableComponent::type, component);
			}
		} else if (componentType == GraphicalComponent::type)
		{
			Pointer<IComponent> component = graphical = CreateGraphicalComponent(entity, attribMap);

			if (component.isValid())
			{
				INode::Map_t::iterator it = m_nodeNames.find(entityName);
				if (it == m_nodeNames.end())
					m_nodeNames[entityName] = graphical->getNode();
			
				if (orientation)
					orientation->getTransformNode()->Push_Back(graphical->getNode());

				entity->RegisterComponent(GraphicalComponent::type, component);
			}
		} else if (componentType == HashedString("EntityController"))
		{
			Pointer<EntityController> controller = CreateEntityController(entity, attribMap);
			m_controllers.push_back(controller);
		}
	}
	m_avatarEntityMap[avatarName].push_back(entity);
	m_entities.insert(Entity::Pair_t(entityName, entity));
	return true;
}
void Game::RetrieveEntity( HashedString entityName, Pointer<Entity>& entity )
{
	Entity::Map_t::iterator it = m_entities.find(entityName);
	if (it != m_entities.end())
		entity = it->second;
}
void Game::RemoveEntity( HashedString entityName )
{
	Entity::Map_t::iterator it = m_entities.find(entityName);
	if (it != m_entities.end())
		m_entities.erase(it);
}
void Game::RemoveEntity( Entity* entity )
{
	for (Entity::Map_t::iterator it = m_entities.begin(); it != m_entities.end(); ++it)
	{
		if ((Entity*)(it->second.getPointer()) == entity)
		{
			m_entities.erase(it);
			break;
		}
	}
}
void Game::CreateController( HashedString entityName )
{
	Pointer<EntityController> controller;
	CreateController( entityName, controller );
}
void Game::CreateController( HashedString entityName, Pointer<EntityController>& controller )
{
	Entity::Map_t::iterator it = m_entities.find(entityName);

	if (it != m_entities.end())
	{
		CreateController(it->second, controller);
	}
}
void Game::CreateController( Entity* entity, Pointer<EntityController>& controller )
{
	controller = new EntityController(entity);

	m_controllers.push_back(controller);
	
	UpdateTask::getSingleton().RegisterUpdatable(controller);
}
void Game::RetrieveController( HashedString entityName, Pointer<EntityController>& controller )
{
	Pointer<Entity> entity;

	Entity::Map_t::iterator eit = m_entities.find(entityName);
	
	if (eit != m_entities.end())
	{
		entity = eit->second;
	
		RetrieveController( entity, controller );
	}
}
void Game::RetrieveController( Pointer<Entity> entity, Pointer<EntityController>& controller )
{
	for (EntityController::Vector_t::iterator it = m_controllers.begin(); it != m_controllers.end(); ++it)
	{
		if ((*it)->getEntity() == entity)
		{
			controller = *it;
			break;
		}
	}
}
void Game::CreateBehavior( HashedString type, EntityController* controller, Pointer<IBehavior>& behavior )
{
	IBehavior::CreatorMap_t::iterator it = m_behaviorCreators.find(type);
	if (it != m_behaviorCreators.end())
		behavior = (*it->second)(controller);
}
void Game::CreateAbility( HashedString type, Combat::Combatant* controller, Pointer<Combat::IAbility>& ability )
{
	Combat::IAbility::CreatorMap_t::iterator it = m_abilityCreators.find(type);
	if (it != m_abilityCreators.end())
		ability = (*it->second)(controller);
}
void Game::CreateEffect( HashedString type, Combat::Combatant* controller, Pointer<Combat::IEffect>& effect )
{
	Combat::IEffect::CreatorMap_t::iterator it = m_effectCreators.find(type);
	if (it != m_effectCreators.end())
		effect = (*it->second)(controller);
}
void Game::CreateUniformInstruction( HashedString type, Pointer<IUniformInstruction>& instruction )
{
	IUniformInstruction::CreatorMap_t::iterator it = m_uniformInstructions.find(type);
	if (it != m_uniformInstructions.end())
		instruction = (*it->second)();
}

void Game::RemoveController( HashedString entityName )
{	
	Pointer<Entity> entity;

	Entity::Map_t::iterator eit = m_entities.find(entityName);
	
	if (eit != m_entities.end())
	{
		entity = eit->second;
	
		for (EntityController::Vector_t::iterator it = m_controllers.begin(); it != m_controllers.end(); ++it)
		{
			if ((*it)->getEntity() == entity)
			{
				UpdateTask::getSingleton().RemoveUpdateable(*it);
				m_controllers.erase(it);
				break;
			}
		}
	}
}
void Game::RemoveController( EntityController* controller )
{	
	for (EntityController::Vector_t::iterator it = m_controllers.begin(); it != m_controllers.end(); ++it)
	{
		if ((EntityController*)(it->getPointer()) == controller)
		{
			UpdateTask::getSingleton().RemoveUpdateable(*it);
			m_controllers.erase(it);
			break;
		}
	}
}
void Game::RemoveController( Entity* entity )	
{
	for (EntityController::Vector_t::iterator it = m_controllers.begin(); it != m_controllers.end(); ++it)
	{
		if ((*it)->getEntity() == entity)
		{
			UpdateTask::getSingleton().RemoveUpdateable(*it);
			m_controllers.erase(it);
			break;
		}
	}
}
void Game::SetEntitySelectable( HashedString entityName )
{
	Pointer<Entity> entity;

	Entity::Map_t::iterator eit = m_entities.find(entityName);
	
	if (eit != m_entities.end())
	{
		entity = eit->second;

		SetEntitySelectable( entity );
	}
}
void Game::SetEntitySelectable( Pointer<Entity>& entity )
{
	SelectableComponent* selectable = (SelectableComponent*)(entity->FindComponent(SelectableComponent::type));

	if (selectable)
		m_selectables->AddRigidBody(selectable->getBody());
}
void Game::SetEntityUnselectable( HashedString entityName )
{
	Pointer<Entity> entity;

	Entity::Map_t::iterator eit = m_entities.find(entityName);
	
	if (eit != m_entities.end())
	{
		entity = eit->second;

		SetEntityUnselectable(entity);
	}
}
void Game::SetEntityUnselectable( Pointer<Entity>& entity )
{
	SelectableComponent* selectable = (SelectableComponent*)(entity->FindComponent(SelectableComponent::type));

	if (selectable)
		m_selectables->RemoveRigidBody(selectable->getBody());
}
void Game::SetEntityGroup( HashedString groupName, HashedString entityName )
{	
	Pointer<Entity> entity;

	Entity::Map_t::iterator eit = m_entities.find(entityName);
	
	if (eit != m_entities.end())
	{
		entity = eit->second;
		SetEntityGroup( groupName, entity );
	}
}
void Game::SetEntityGroup( HashedString groupName, Entity* entity )
{
	m_entityGroups[groupName].push_back(entity);
}
void Game::RemoveEntityFromAllGroups( HashedString entityName )
{
	Pointer<Entity> entity;

	Entity::Map_t::iterator eit = m_entities.find(entityName);
	
	if (eit != m_entities.end())
	{
		entity = eit->second;
		RemoveEntityFromAllGroups( entity );
	}
}
void Game::RemoveEntityFromAllGroups( Entity* entity )
{
	for (std::map<HashedString, std::list<Entity*>>::iterator group = m_entityGroups.begin(); group != m_entityGroups.end(); ++group)
	{
		std::list<Entity*>& entities = group->second;
		for (std::list<Entity*>::iterator entityList = entities.begin(); entityList != entities.end(); ++entityList)
		{
			if (*entityList == entity)
			{
				entities.erase(entityList);
				break;
			}
		}
	}
}
void Game::AddEntityToPathingWorld( HashedString worldName, HashedString entityName )
{
	Pointer<Entity> entity;
	Pointer<EntityController> controller;

	Entity::Map_t::iterator eit = m_entities.find(entityName);
	
	if (eit != m_entities.end())
	{
		entity = eit->second;
	
		for (EntityController::Vector_t::iterator it = m_controllers.begin(); it != m_controllers.end(); ++it)
		{
			if ((*it)->getEntity() == entity)
			{
				controller = *it;
				controller->setWorld(m_pathingWorlds[worldName]);
				break;
			}
		}
	}
}
void Game::AddEntityToPathingWorld( HashedString worldName, Pointer<Entity>& entity )
{
	Pointer<EntityController> controller;
	
	for (EntityController::Vector_t::iterator it = m_controllers.begin(); it != m_controllers.end(); ++it)
	{
		if ((*it)->getEntity() == entity)
		{
			controller = *it;
			controller->setWorld(m_pathingWorlds[worldName]);
			break;
		}
	}
}
void Game::RemoveEntityFromPathingWorld( HashedString worldName, HashedString entityName )
{
	Pointer<Entity> entity;
	Pointer<EntityController> controller;

	Entity::Map_t::iterator eit = m_entities.find(entityName);
	
	if (eit != m_entities.end())
	{
		entity = eit->second;
	
		for (EntityController::Vector_t::iterator it = m_controllers.begin(); it != m_controllers.end(); ++it)
		{
			if ((*it)->getEntity() == entity)
			{
				controller = *it;
				controller->setWorld(Pointer<Pathing::World>(0));
				break;
			}
		}
	}
}
void Game::AddEntityToSimulationWorld( HashedString worldName, HashedString entityName )
{
	Pointer<Entity> entity;
	Pointer<EntityController> controller;

	Entity::Map_t::iterator eit = m_entities.find(entityName);
	
	if (eit != m_entities.end())
	{
		entity = eit->second;
		AddEntityToSimulationWorld( worldName, entity );
	}
}
void Game::AddEntityToSimulationWorld( HashedString worldName, Pointer<Entity>& entity )
{
	// RigidBodyComponent
	RigidBodyComponent* rigidbody = (RigidBodyComponent*)(entity->FindComponent(RigidBodyComponent::type));

	System* world = PhysicsTask::getSingleton().FindSystem(worldName);
	if (world)
		world->AddRigidBody(rigidbody->getBody());
}
void Game::RemoveEntityFromSimulationWorld( HashedString worldName, HashedString entityName )
{
	Pointer<Entity> entity;
	Pointer<EntityController> controller;

	Entity::Map_t::iterator eit = m_entities.find(entityName);
	
	if (eit != m_entities.end())
	{
		entity = eit->second;
		RemoveEntityFromSimulationWorld( worldName, entity );
	}
}
void Game::RemoveEntityFromSimulationWorld( HashedString worldName, Pointer<Entity>& entity )
{
	// RigidBodyComponent
	RigidBodyComponent* rigidbody = (RigidBodyComponent*)(entity->FindComponent(RigidBodyComponent::type));

	System* world = PhysicsTask::getSingleton().FindSystem(worldName);
	if (world)
		world->RemoveRigidBody(rigidbody->getBody());
}
	
// Pathing
void Game::CreatePathingWorld( HashedString worldName )
{
	m_pathingWorlds.insert(Pathing::World::Pair_t(worldName, new Pathing::World()));
}
void Game::CreatePathingWorld( HashedString worldName, Pointer<Pathing::World>& world )
{
	world = new Pathing::World();
	m_pathingWorlds.insert(Pathing::World::Pair_t(worldName, world));
}
void Game::RetrievePathingWorld( HashedString worldName, Pointer<Pathing::World>& world )
{
	Pathing::World::Map_t::iterator it = m_pathingWorlds.find( worldName );
	if (it != m_pathingWorlds.end())
		m_pathingWorlds.erase(it);
}
	
// Simulations
void Game::CreateSimulationWorld( HashedString worldName )
{
	System* world;
	CreateSimulationWorld( worldName, world );
}
void Game::CreateSimulationWorld( HashedString worldName, System*& world )
{
	world = new System();
	world->Initialize();

	PhysicsTask::getSingleton().AddSystem(worldName, world);
}
void Game::RetrieveSimulationWorld( HashedString worldName, System*& world )
{
	world = PhysicsTask::getSingleton().FindSystem(worldName);
}

// SceneGraph
void Game::RememberNode( HashedString nodeName, Pointer<INode> node )
{
	if (node.isValid())
		m_nodeNames[nodeName] = node;
}
void Game::RetrieveNode( HashedString nodeName, Pointer<INode>& node )
{
	INode::Map_t::iterator it = m_nodeNames.find(nodeName);
	if (it != m_nodeNames.end())
		node = it->second;
}
void Game::ForgetNode( HashedString nodeName )
{
	INode::Map_t::iterator it = m_nodeNames.find(nodeName);
	if (it != m_nodeNames.end())
		m_nodeNames.erase(it);
}

// Utility
bool Game::RetrieveEntityGroup( HashedString groupName, std::list<Entity*>*& list )
{
	std::map<HashedString, std::list<Entity*>>::iterator it = m_entityGroups.find(groupName);
	if (it != m_entityGroups.end())
	{
		list = &(it->second);
		return true;
	}
	return false;
}
bool Game::isEntityWithinGroup( HashedString groupName, Entity* entity )
{
	std::map<HashedString, std::list<Entity*>>::iterator it = m_entityGroups.find(groupName);
	if (it != m_entityGroups.end())
	{
		std::list<Entity*>& entities = it->second;
		return (std::find(entities.begin(), entities.end(), entity) != entities.end());
	}
	return false;
}
bool Game::EntityExists( Entity* entity )
{
	for (Entity::Map_t::iterator it = m_entities.begin(); it != m_entities.end(); ++it)
	{
		if ((Entity*)(it->second.getPointer()) == entity)
			return true;
	}
	return false;
}
bool Game::LoadFromFile( std::string filename )
{
	return Serialize::Load(filename);
}
bool Game::SaveToFile( std::string filename )
{
	return Serialize::Save(filename);
}
Entity* Game::Select( int x, int y )
{
	Entity* entity = 0;
	Maths::Vector3D from;
	Maths::Vector3D to;

	m_activeCamera->Unproject((float)x, (float)y, from, to);

	if (m_selectables->RayCast(from, to, (void**)&entity))
	{
		return entity;
	}
	return 0;
}
Entity* Game::Select( int x, int y, Maths::Vector3D& point )
{
	Entity* entity = 0;
	Maths::Vector3D from;
	Maths::Vector3D to;

	m_activeCamera->Unproject((float)x, (float)y, from, to);

	if (m_selectables->RayCastGetPoint(from, to, (void**)&entity, point))
		return entity;
	return 0;
}
Pointer<CameraNode> Game::RetrieveActiveCamera()
{
	return m_activeCamera;
}
void Game::setActiveCamera( Pointer<CameraNode>& cameraNode )
{
	if (cameraNode.isValid())
		m_activeCamera = cameraNode;
}
void Game::RegisterCamera( HashedString cameraName, Pointer<CameraNode>& cameraNode, bool setActive )
{
	Pointer<INode> node;
	CopyPointer(cameraNode, node);

	m_nodeNames.insert(INode::Pair_t(cameraName, node));

	if (setActive)
		m_activeCamera = cameraNode;
}

// System functions - avoid use
Entity::Map_t& Game::_getAllEntities()
{
	return m_entities;
}
Pointer<System>& Game::_getSelectables()
{
	return m_selectables;
}
std::vector<std::string>& Game::_getTextureStrings()
{
	return m_textureStrings;
}
EntityController::Vector_t& Game::_getControllers()
{
	return m_controllers;
}
Pathing::World::Map_t& Game::_getPathingWorlds()
{
	return m_pathingWorlds;
}
Pointer<CameraNode>& Game::_getActiveCamera()
{
	return m_activeCamera;
}
std::map<HashedString, std::vector<Entity*>>& Game::_getAvatarEntityMap()
{
	return m_avatarEntityMap;
}